/*******************************************************************************
 * @file Copyright 2009 The CREATE Lab at CMU
 * 
 *       This file is part of JubJub, an open source project.
 *       http://code.google.com/p/jubjub/
 * 
 *       Redistribution and use in source and binary forms, with or without
 *       modification, are permitted provided that the following conditions are
 *       met:
 * 
 *       Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 * 
 *       Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 * 
 *       Neither the name of Carnegie Mellon nor the names of its contributors
 *       may be used to endorse or promote products derived from this software
 *       without specific prior written permission.
 * 
 *       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *       "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *       LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *       HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *       SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *       LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *       OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

package edu.cmu.ri.createlab.jj.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.ScrollPane;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.LinkedList;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import edu.cmu.ri.createlab.jj.blocks.*;
import edu.cmu.ri.createlab.jj.projects.JJProject;
import edu.cmu.ri.createlab.jj.shapes.*;
import edu.cmu.ri.createlab.jj.visitors.*;
import static edu.cmu.ri.createlab.jj.shapes.ShapeDefs.*;

public class WorkPanel extends JPanel implements JJPanelInterface, MouseListener, MouseMotionListener
{
   private BlockShape currBlock;
   private double scale;
   private BVDrawer drawer;
   private LinkedList<RefBlock> dragBlocks;
   private int pressX, pressY;
   private boolean dragStart;
   private boolean drawYellow;
   private int dyType;
   protected javax.swing.event.EventListenerList listenerList =
      new javax.swing.event.EventListenerList();
   
   public void addJJDragReadyListener(JJDragReadyListener listener)
   {
      listenerList.add(JJDragReadyListener.class, listener);
   }
   
   // This methods allows classes to unregister for MyEvents
   public void removeJJDragReadyListener(JJDragReadyListener listener) 
   {
       listenerList.remove(JJDragReadyListener.class, listener);
   }

// This private class is used to fire MyEvents
   void fireJJDragReadyEvent(JJDragReadyEvent evt) 
   {
       Object[] listeners = listenerList.getListenerList();
       // Each listener occupies two elements - the first is the listener class
       // and the second is the listener instance
       for (int i=0; i<listeners.length; i+=2) {
           if (listeners[i]==JJDragReadyListener.class) {
               ((JJDragReadyListener)listeners[i+1]).jjDragReadyOccurred(evt);
           }
       }
   }
   
   public LinkedList<RefBlock> getDragBlocks()
   {
      return dragBlocks;
   }

   
   
   public BlockVisitorInterface[] getVisitors()
   {
      // TODO Auto-generated method stub
      return null;
   }
   
   public WorkPanel(BVDrawer drawer)
   {
      this.drawer = drawer;
      scale = 0.75;
      currBlock = null;
      this.setPreferredSize(new Dimension(800, 600));
      this.setLayout(null);
      this.setBackground(Color.white);
      this.addMouseListener(this);
      this.addMouseMotionListener(this);
      dragStart = false;
      drawYellow = false;
      dyType = 0;
   }
   
   public void setBlock(BlockBlock block)
   {
      this.removeAll();
      currBlock = new BlockShape(block, scale, this);
      this.setPreferredSize(new Dimension(800, Math.max(600,currBlock.getBounds()[3]+40)));
      this.repaint();
   }
   
   public BlockBlock getBlock()
   {
      return currBlock.getBlock();
   }

   public void paintComponent(Graphics g)
   {
      super.paintComponent(g);
      if(currBlock != null) 
      {
         int dx =  (int)(MouseInfo.getPointerInfo().getLocation().x -this.getLocationOnScreen().x);
         int dy =  (int)(MouseInfo.getPointerInfo().getLocation().y -this.getLocationOnScreen().y);
         currBlock.setDY(drawYellow, dx, dy, dyType);
         currBlock.draw(g, this, drawer);
      }
   }
   
   public static void main(String[] args)
   {
      BVDrawer drawer = new BVDrawer();
      WorkPanel wp = new WorkPanel(drawer);
      wp.setBlock((BlockBlock) JJProject.getTestProject().getClasses().get(0).getMethodBlocks().get(1));
      JScrollPane sp = new JScrollPane();
      Dimension d1 = new Dimension(800,600);
      sp.setPreferredSize(d1);
      sp.setViewportView(wp);
      
      JFrame frame = new JFrame("BVDrawer test");
      
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(sp);
      
      frame.pack();
      
      frame.setVisible(true);
   }

   
   public void mouseClicked(MouseEvent arg0)
   {
      // TODO Auto-generated method stub
      
   }

   
   public void mouseEntered(MouseEvent arg0)
   {
      // TODO Auto-generated method stub
      
   }

   
   public void mouseExited(MouseEvent arg0)
   {
      // TODO Auto-generated method stub
      
   }
   
   public void addBlocks(LinkedList<RefBlock> blocks, int x, int y)
   {
//      int x = (int)this.getMousePosition().getX();
//      int y = (int)this.getMousePosition().getY();
      currBlock.addBlocks(blocks, x, y);
      setBlock(currBlock.getBlock());
      revalidate();
   }

   
   public void mousePressed(MouseEvent arg0)
   {
      // TODO Auto-generated method stub
//      RefBlock ref = currBlock.getRef(arg0.getX(), arg0.getY());
//      if(ref == null) return;
//      dragBlocks = new LinkedList<RefBlock>();
//      dragBlocks.add(ref);
      System.out.println("Work Press");
      pressX = MouseInfo.getPointerInfo().getLocation().x - this.getLocationOnScreen().x; //arg0.getX();
      pressY = MouseInfo.getPointerInfo().getLocation().y - this.getLocationOnScreen().y; //arg0.getY();
      dragStart = true;
   }

   
   public void mouseReleased(MouseEvent arg0)
   {
      // TODO Auto-generated method stub
      if(dragStart && arg0.getClickCount() == 2)
      {
         currBlock.clicked(pressX, pressY);
      }
      drawYellow = false;
      dragStart = false;
      this.repaint();
   }

   public void setDYType(int type)
   {
      dyType = type;
   }
   
   public void mouseDragged(MouseEvent arg0)
   {
      System.out.println("Dragged");
      int currx = MouseInfo.getPointerInfo().getLocation().x - this.getLocationOnScreen().x;
      int curry = MouseInfo.getPointerInfo().getLocation().y - this.getLocationOnScreen().y;
      if(dragStart && 
            (Math.abs(currx-pressX) > 5 
                  || Math.abs(curry-pressY) > 5))
      {
         dragStart = false;
         dragBlocks = currBlock.getRefs(pressX, pressY);
         setBlock(currBlock.getBlock());
         fireJJDragReadyEvent(new JJDragReadyEvent(this));
      }
      else
      {
         drawYellow = true;
         this.repaint();
      }
      int dY = MouseInfo.getPointerInfo().getLocation().y-getParent().getParent().getLocationOnScreen().y;
      int yDist = getParent().getParent().getHeight()-scrollDist;
      System.out.println("dy = " + dY + " dist: " + yDist);
      if(dY < scrollDist)
      {
         javax.swing.JScrollBar sb = ((JScrollPane)getParent().getParent()).getVerticalScrollBar();
         sb.setValue(Math.max(0, sb.getValue()-2));
      }
      if(dY > yDist)
      {
         System.out.println("scroll down");
         javax.swing.JScrollBar sb = ((JScrollPane)getParent().getParent()).getVerticalScrollBar();
         sb.setValue(Math.min(sb.getMaximum(), sb.getValue()+2));
      }
   }

   
   public void mouseMoved(MouseEvent arg0)
   {
      // TODO Auto-generated method stub
      
   }
}
